package com.edianping.main;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.net.*;

import java.rmi.registry.LocateRegistry;
import java.rmi.Naming;
import java.rmi.server.UnicastRemoteObject;

import org.apache.log4j.Logger;

import com.daguu.lib.httpsqs4j.Httpsqs4j;
import com.daguu.lib.httpsqs4j.HttpsqsClient;
import com.daguu.lib.httpsqs4j.HttpsqsException;
import com.edianping.bean.ProcessItemBean;
import com.edianping.config.AppConfigBean;
import com.edianping.config.ConstVars;
import com.edianping.timer.Timer;
import com.edianping.util.XmlUtil;

/**
 * 封装<code>java.util.Timer</code>，调度<code>MainTask</code>
 * 这里的主要问题就是再运行后再改变程序的间隔就不好弄了，需要重新创建 Timer和TimerTask对象，重新启动任务， 这个就比较麻烦了。
 * 
 * @author jszhang
 * 
 */
public class MainTaskHandle implements IRemoteMainTask {

//	private ConnectionPool connPool = null;
	private Timer timer;
	private MainTask maintask;
	private HttpsqsClient client;
	
	private AppConfigBean acb;
	
	private static Logger log = Logger.getLogger(MainTaskHandle.class);
	
	public MainTaskHandle( AppConfigBean appcfg, BlockingQueue<ProcessItemBean> toProcess, BlockingQueue<ProcessItemBean> processed ) {
		if ( appcfg == null )
			return;
		// 整个程序的connPool在这里初始化
		// 以后再调用getInstance是没效果的
//		connPool = ConnectionPool.getInstance(wsb.connpoosize);
		
		try {
			Httpsqs4j.setConnectionInfo("localhost", 1218, "UTF-8");
		} catch (HttpsqsException e) {
			e.printStackTrace();
		}
		HttpsqsClient client = Httpsqs4j.createNewClient();
		
		this.acb = appcfg;
		
		//three main process here
		maintask = new MainTask( acb, client );
	}

	/**
	 *这里启动所有的Tasks
	 **/
	public void start() {
		timer = new Timer();
		timer.schedule( maintask, 0, maintask.interval * 1000 );
	}

	/**
	 *重新读入所有Tasks，并且启动
	 **/
	public void restart() {
		// Stop Timer and stop thread
		cancel();
		
		// Clear Running thread
		maintask.tp_handle.clearPool();
		maintask.MaxIterNum = 1;

		maintask = new MainTask( acb, client );
		timer.schedule( maintask, 0, maintask.interval * 1000 );
	}

	/**
	 * 这个是等线程池那里完全执行完毕才能停止 cancel之后原来的task也就算是挂了，不能再用了，实在要用就改task里面的状态吧 ^_^
	 */
	public void cancel() {
		maintask.cancel();
		timer.purge();
	}

	/**
	 * 这个需要清除线程池中的队列的，否则无法停止的
	 * 
	 * @throws
	 */
	public void stop() {
		/*
		 * for(MainTask task: tasklist){ task.tp_handle.softShundown(5);
		 * //仁慈一点，10秒钟后结束线程池 task.cancel(); }
		 */
		maintask.tp_handle.softShundown(5);
		timer.purge();
		
		System.exit(0);
	}

	/**
	 *如果使用了ThreadPoolHandle 构造函数中的 pool.allowCoreThreadTimeOut(true);
	 * 那么pause久了线程池中的线程都中止了，那样会造成pause时的任务丢失了
	 */
	public void pause() {
		
		maintask.tp_handle.pause();
	}
	
	public String status() {
		String result = "";
		
		return result;
	}

	public long getCurrentPoolQueenSize() {
		return maintask.tp_handle.getCurrentQueueSize();
	}

	public long getCurrentPoolSize() {
		return maintask.tp_handle.getPoolSize();
	}

	/**
	 * 暂停的恢复
	 */
	public void resume() {
		/*
		 * for(MainTask task: tasklist){ task.tp_handle.resume(); }
		 */
		maintask.tp_handle.resume();
		
//		dbreader.resume();
//		dbwriter.resume();
	}

	/**
	 * Crawler 的Main函数 args[0] 给定当前机器的IP，用于远程连接，监控运行状态
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		
		BlockingQueue<ProcessItemBean> toProcess = new LinkedBlockingQueue<ProcessItemBean>();
		BlockingQueue<ProcessItemBean> processed = new LinkedBlockingQueue<ProcessItemBean>();
		
		try {
			AppConfigBean acb = XmlUtil.parse2wsb( ConstVars.CONFIGURE_FILE );
			MainTaskHandle handle = new MainTaskHandle( acb, toProcess, processed );
			
			IRemoteMainTask stub = (IRemoteMainTask) UnicastRemoteObject
					.exportObject(handle, 0);

			//remote method invocation
			LocateRegistry.createRegistry(8808); // 注册端口
			Naming.rebind("//" + InetAddress.getLocalHost().getHostAddress() + ":8808/backend", stub); // 将实现类绑到一个名字上去

			log.info( InetAddress.getLocalHost().getHostAddress() + " Server ready" );
			handle.start();

		} catch (Exception e) {
			System.err.println("Server exception: " + e.toString());
			e.printStackTrace();
		}
	}

}
